#![feature(nll)]
#![feature(never_type)]
extern crate sdl2;
extern crate rand;
extern crate weak_table;

pub mod geom;
pub mod frag;
pub mod diff;
pub mod tree;
pub mod gui;
pub mod signal;

mod app {
  use sdl2::pixels::{Color};
  use geom;
  use gui;
  use gui::{GUI, Component, PureComponent};
  use frag;
  use frag::AlignH::*;
  use frag::AlignV::*;

  #[derive(Eq, PartialEq)]
  struct Square { size: u32 }

  impl gui::Component for Square {
    type State = u32;

    fn init(&self) -> u32 { self.size }

    fn render(&self, ctx: gui::Ctx<Self>) -> GUI {
      let color = match self.size {
        0...40 =>  Color::RGB(255, 0, 40),
        40...50 => Color::RGB(0, 120, 240),
        _ =>       Color::RGB(255, 240, 0),
      };

      let area = frag::fill(color)
        .on_click(ctx.callback(|path, &()| {
          print!("click! path={:?}\n", path);
        }));

      area.container()
          .width(self.size)
          .height(self.size)
          .into()
    }
  }

  #[derive(Eq, PartialEq)]
  struct Window { elems: Vec<gui::GUI> }

  impl PureComponent for Window {
    fn render(&self) -> GUI {
      gui::pack_lr(self.elems.clone())
        .align(Left, Top)
        .underlay(gui::fill(Color::RGB(255, 255, 255)))
        .container()
        .bounds(geom::Dim(600, 400))
        .align(Center, Middle)
    }
  }

  pub fn create() -> GUI {
    Window {
      elems: [40, 50, 60]
        .iter()
        .map(|&size| Square { size }.into_gui())
        .collect()
    }.into_gui()
  }
}

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

fn main() {
  let sdl = sdl2::init().unwrap();
  let mut events = sdl.event_pump().unwrap();

  let vid = sdl.video().unwrap();
  let mut canvas: sdl2::render::Canvas<_> =
    vid.window("R", 800, 600)
       .build()
       .unwrap()
       .into_canvas()
       .build()
       .unwrap();

  let mut ui = gui::LiveGUI::new(
    geom::Dim(800, 600),
    app::create(),
  );

  'renderloop: loop {
    for evt in events.poll_iter() {
      use sdl2::event::{Event, WindowEvent};
      match evt {
        Event::Quit { .. } =>
          break 'renderloop,

        Event::Window { win_event: WindowEvent::Resized(w, h), .. } =>
          ui.set_size(geom::Dim(w as u32, h as u32)),

        Event::MouseButtonDown { x, y, .. } => {
          let mouse_pos = geom::Pos(x as _, y as _);
          ui.fire_click_evt(mouse_pos);
        }

        _ =>
          (),
      }
    }

    {
      use frag::{DrawFrag};

      canvas.set_draw_color(sdl2::pixels::Color::RGB(0, 0, 0));
      canvas.clear();
      canvas.draw_frag(ui.root_frag());
      canvas.present();
      std::thread::sleep(
        std::time::Duration::from_micros(1000000 / 64)
      );
    }
  }
}

/*
fn timed<F, T>(f: F) -> T where F: FnOnce() -> T {
  use std::time::{Instant};
  let start = Instant::now();
  let ret = f();
  print!("{:?}\n", Instant::now() - start);
  ret
}
*/
